﻿using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;
using System.Text;
using System.Web;
using System.Xml;
using System.Xml.Linq;
using System.Xml.Serialization;


namespace FlexySys.Common.Extension
{
    public static class Extensions
    {
        public static int? ToInt(this object obj)
        {
            if (obj == null)
                return null;
            int i = 0;
            if (int.TryParse(obj.ToString(), out i))
                return i;
            else
                return null;
        }
        public static int? ToInt(this string str)
        {
            if (string.IsNullOrEmpty(str))
                return null;
            int i = 0;
            if (int.TryParse(str, out i))
                return i;
            else
                return null;
        }
        public static string GetString(this object obj)
        {
            if (obj == null)
                return string.Empty;
            else
                return obj.ToString();
        } 

        public static bool ToBoolean(this object obj)
        {
            if (obj == null)
                return false;
            else
            {
                bool b = false;
                bool.TryParse(obj.ToString().ToLower(), out b);
                return b;
            }
        }

        public static Guid? ToGuid(this string obj)
        {
            if (string.IsNullOrEmpty(obj))
                return null;

            return new Guid(obj);
        }

        public static T ToEnum<T>(this string val)
        {
            try
            {
                return (T)Enum.Parse(typeof(T), val);
            }
            catch { return default(T); }
        }

        public static T ToEnum<T>(this int? val)
        {
            if (val.HasValue)
            {
                try
                {
                    return (T)Enum.ToObject(typeof(T), val);
                }
                catch { return default(T); }
            }
            else
                return (T)Enum.ToObject(typeof(T), 0);
        }
        
        //public static bool ContainsBy<T>(this IEnumerable<T> list, T item, Func<T, object> keyExtractor)
        //{
        //    return list.Contains(item, new KeyEqualityComparer<T>(keyExtractor));
        //}

        public static void SetPropertyValue(this object obj, string propertyName, object propertyValue)
        {

            PropertyInfo pi = obj.GetType().GetProperty(propertyName);
            if (pi == null)
                return;
            pi.SetValue(obj, propertyValue, null);

        }

        #region DataTable

        public static XElement ToXml(this DataTable table)
        {
            if (table == null)
                return null;

            if (table.DataSet != null)
                return table.DataSet.ToXml();
            else
            {
                table.TableName = "Row";
                DataSet ds = new DataSet();
                ds.Tables.Add(table);
                return ds.ToXml();
            }

        }

        public static XElement ToXml(this DataSet ds)
        {
            ds.DataSetName = "Table";
            StringWriter sw = new StringWriter();
            ds.WriteXml(sw, XmlWriteMode.WriteSchema);
            return XElement.Parse(sw.ToString());
        }

        public static DataTable ToDataTable(this XElement xElement)
        {
            DataSet ds = new DataSet();
            ds.ReadXml(new XmlTextReader(new StringReader(xElement.ToString())));

            return ds.Tables[0];
        }

        public static DataTable FieldToDataTable(this XElement xElement)
        {
            return xElement.Element("Value").Element("Table").ToDataTable();
        }

        public static DataTable ToDataTable(this string xml)
        {
            XElement xElement = XElement.Parse(xml);
            return xElement.ToDataTable();
        }

        #endregion

        //public static DateTime UtcToUserDateTime(this DateTime datetime)
        //{

        //    BaseUser bu = Web.Core.Sessions<BaseUser>.Get();
        //    if (bu != null && bu.TimeZone != null && datetime != DateTime.MinValue)
        //        return datetime.Add(bu.TimeZone.BaseUtcOffset);
        //    else
        //        return datetime;
        //}

        //#region DevExpress.Data.UnboundColumnType
        //public static Type ToType(this DevExpress.Data.UnboundColumnType type)
        //{
        //    Type t = null;
        //    switch (type)
        //    {
        //        case DevExpress.Data.UnboundColumnType.Boolean:
        //            {
        //                t = typeof(bool);
        //            }
        //            break;
        //        case DevExpress.Data.UnboundColumnType.DateTime:
        //            {
        //                t = typeof(DateTime);
        //            }
        //            break;
        //        case DevExpress.Data.UnboundColumnType.Decimal:
        //            {
        //                t = typeof(decimal);
        //            }
        //            break;
        //        case DevExpress.Data.UnboundColumnType.Integer:
        //            {
        //                t = typeof(int);
        //            }
        //            break;
        //        case DevExpress.Data.UnboundColumnType.String:
        //            {
        //                t = typeof(string);
        //            }
        //            break;
        //        default:
        //            {
        //                t = typeof(object);
        //            }
        //            break;
        //    }
        //    return t;
        //}
        //#endregion

        public static XElement ToXElement<T>(this object obj)
        {
            using (var memoryStream = new MemoryStream())
            {
                using (TextWriter streamWriter = new StreamWriter(memoryStream))
                {
                    var xmlSerializer = new XmlSerializer(typeof(T));
                    xmlSerializer.Serialize(streamWriter, obj);
                    return XElement.Parse(Encoding.UTF8.GetString(memoryStream.ToArray()));
                }
            }
        }

        public static T FromXElement<T>(this XElement xElement)
        {
            using (var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(xElement.ToString())))
            {
                var xmlSerializer = new XmlSerializer(typeof(T));
                return (T)xmlSerializer.Deserialize(memoryStream);
            }
        }
    }
}